بسم الله الرحمن الرحيم




الدخــول

الكنية

كلمة المرور

لم تسجل بعد؟ تستطيع التسجيل. بعد التسجيل يمكنك تغيير شكل الموقع, والتحكم في التعليقات وإرسال تعليقات بإسمك


مواقع صديقة

شبكة المطورون العرب

دوت نت للعرب







صمم Microsoft Excel بنفسك !!!

مقالات ودروس عامة


عندما تسبح في خلايا جداول Microsoft Excel، يراودك ذلك الفضول العجيب وتتكاثر الاسئلة -من خصالك كمبرمج- كيف تم تصميم هذا البرنامج؟؟ كيف يمكن لهذا البرنامج ان يعرض لك آلاف الخلايا ويحفظها لك في ملفات دون استهلاك هذه المساحة الكبيرة؟ وكيف يقوم برتيب المدخلات في خلايا على شكل جداول؟ وكيف ... وكيف ... الخ من الاسئلة التي تثير اهتمامات المبرمجين. في السطور التالية سنقوم بتصميم برنامج بسيط لعرض الجداول الممتدة اسميته VB4ARAB Excel.


في البداية عليك معرفة ان برنامج Microsoft Excel قام بتطويره اكثر من 200 مبرمج محترف واستغرق شهور عدة لاتمامه، بالاضافة الى الدعم المادي والمعنوي من قبل كبريات شركات تطوير البرامج Microsoft. اما برنامجنا VB4ARAB فلم يصممه الا مبرمج واحد متوسط الخبرة، واستغرق يومين، فارجو ان تقتنع فيه رغم البساطة التي قد تجدها في البرنامج. مع ذلك، توجد ثلاثة مزايا في برنامج VB4ARAB Excel ليست موجودة في Microsoft Excel وهي:

1) في Microsoft Excel العدد الاقصى من الاعمدة هو 256 والعدد الاقصى من السطور Rows هو 65536، بينما Vb4arab Excel فالعدد الاقصى للاعمدة يتجاوز 2147483647 وهو نفس العدد الاقصى للسطور!

2) ان مطوره عربي، ولست بكلمة عربي قاصدا احياء القومية العربية، وانما اقاصد انني وضعت اللغة العربية في عين الاعتبار اثناء تصميم البرنامج، فلن تحتاج الى خاصية RightToLeft او تقنية المرءاة، فـ Vb4arab Excel موجه للمستخدم العربي كما تلاحظ في الشكل التالي:



3) انه برنامج مجاني 100% بل ويمكنك الحصول على شفرته المصدرية بالكامل مكتوبة بلغة VB6، ولم استخدم اجراء واحد من اجراءات API!

الفوائد التي قد تجنيها من متابعة هذا الموضوع ستكون جيدة جدا لك، حيث ستتعلم كيف تطور اداة تحكم ActiveX Control لعرض الجداول اسمها Vb4arabGrid، وستتعلم الطريقة الصحيحة لتقسيم البرنامج، وستتعلم اسلوب التنفيذ عند الطلب On Demand Execution، و التصنيف الفرعي Subclassing للفئات.

اقسام المشروع

قسمت برنامج Vb4arab Excel الى قسمين، القسم الاول هو البرنامج الرئيسي Vb4arab Excel والقسم الثاني خاص لتصميم اداة تحكم لعرض الجداول اسمها VB4arabGrid تحتوي على فئة Class اضافية باسم CData حيث تمكن الجدول من عرض اكثر من صفحة Sheet دون الحاجة الى انشاء نسخة جديدة من الاداة. فلو تلاحظ ان ورقة العمل Workbook الموجودة في Microsoft Excel يمكنها ان تعرض لك اكثر من صفحة Sheet، فلا تعتقد ان مطوروا Microsoft Excel بذلك الحد من الغباء الذي يحدهم الى استخدام اكثر من اداة تحكم، وانما يستخدمون اداة تحكم واحدة فقط لعرض بيانات الصفحات المختلفة كل صفحة لها فئة مستقلة -قد تكون باسم CSheet- وهي نفس الفكرة التي طبقناها في برنامجنا Vb4aab Excel ولكن اسم فئة بيانات الصفحة هو CData. والان لنصمم البرنامج الرئيس، واداة التحكم حيث ستكون البداية مع الفئة CData.

اولا: تصميم الفئة CData
من الاساليب الاحترافية لتصميم البرامج هو فصل كود مخزن البيانات عن كود عرض البيانات، وهذا الاسلوب قد تعلمت منذ زمن طويل عندما كنت ابرمج بـ Visual C، حيث كانت توفر لي مكتبة MFC فئتين الاولى لحفظ البيانات CDocument والاخرى لعرضها CView.
الفئة CData تحتوي على جميع البيانات التي تتعلق بالجدول الحالي، عرض الاعمد، ارتفاع السطور، محتويات الخلايا. وهي مستقلة بحد ذاتها تتبع لاداة التحكم Vb4arabGrid فقط، فاداة التحكم Vb4arab Grid تقوم بقراءة البيانات من هذه الفئة ومن ثم رسمها على شكل جدول.

المشكلة التي ستصادفك هي ان عدد الاعمدة والسطور كبير جدا جدا (يتجاوز 2147483647) وعدد الخلايا اكبر (x2147483647 x 2147483647) فلو قمت بتجهيز مصفوفة لحفظ جميع بيانات الخلايا وعرض الاعمدة واتفاع الخلايا، فقد تحتاج الى 20 خادم Server لحفظ بيانات جدولك. لذلك دعنا نحفظ القيم التي قام المستخدم بتعديلها فقط، اما القية قستحتوي على قيم افتراضية Default Valuse، وهذا الذي فعلته بالضبط في الفئة CData:

code:
Public iColDefaultWidth As Integer     ' العرض الافتراضي للعمود
Public iRowDefaultHeight As Integer     ' الارتفاع الافتراضي للسطر
Private ColsProp() As ColPropUDT      ' خصائص الاعمدة
Private RowsProp() As RowPropUDT      ' خصائص السطور
Private CellsProp() As CellPropUDT      ' خصائص الخلايا


فعندما تقوم اداة التحكم بالاستعلام عن ارتفاع السطر 2 مثلا، سنرى ما اذا كان السطر 2 موجود في المصفوفة ( )RowsProp لنعود بقيمة ارتفاع السطر، وان لم يقم المستخدم بتعديل ارتفاع السطر، فسنعود بقيمة افتراضية يحملها المتغير iRowDefaultHeight. وستجد هذا الكود في الخاصية RowHeight:

code:
Friend Property Get RowHeight(ByVal lRowNum As Long) As Long
    ' سنبحث عن ارتفاع السطر في مصفوفة خصائص السطور
    ' وان لم نجده سنعود بالقيمة الافتراضية
    
    Dim iCounter As Integer
       
    For iCounter = 0 To UBound(RowsProp)
        If RowsProp(iCounter).lRowNum = lRowNum Then
            RowHeight = RowsProp(iCounter).iRowHeight
            Exit Property
        End If
    Next
    RowHeight = iRowDefaultHeight
End Property


في الكود السابق استخدم خوارزم البحث المتتالي Sequential Search، وقد تزيد سرعة عملية البحث باستخدام البحث الثنائي Binary Search او البحث Hash Search، ولكن عليك معرفة ان البحث الثنائي Binary Search لا يعطي نتائج صحيحة الا في حالة كون القيم الموجودة في المصفوفة مرتبة تصاعديا او تنازليا.

يمكنك تعيين قيمة جديدة الى الخاصية RowHeight، وذلك بالبحث اولا عن العنصر الموجود في المصفوفة ومن ثم اسناد القيمة الجديدة له، وان لم تجد العنصر المطلوب، اضف عنصر جديد الى المصفوفة RowsProp باستخدام Redim Preserve:
code:
Friend Property Let RowHeight(ByVal lRowNum As Long, ByVal lNewValue As Long)
    ' سنبحث عن السطر في مصفوفة خصائص السطور
    ' وان لم نجده سنضيف عنصر جديد
    
    Dim iCounter As Integer
       
    For iCounter = 0 To UBound(RowsProp)
        If RowsProp(iCounter).lRowNum = lRowNum Then
            RowsProp(iCounter).iRowHeight = lNewValue
            Exit Property
        End If
    Next
    
    ' اضافة عنصر جديد في مصفوفة السطور
    ReDim Preserve RowsProp(UBound(RowsProp) + 1)
    
    RowsProp(UBound(RowsProp)).lRowNum = lRowNum
    RowsProp(UBound(RowsProp)).iRowHeight = lNewValue
End Property

تلاحظ انني اعتمدت على المصفوفات في الفئة CData عوضا عن المجموعات Collection، والسبب محاولة تقليص المساحة المطلوبة في الذاكرة وزيادة السرعة، فالمجموعات Collection شرهة جدا في اكل بايتات الذاكرة، كما ان سرعتها ابطأ 20 مرة من المصفوفات.
ينقص الفئة CData شئ واحد تقريبا وهي امكانية حذف محتويات العنصر، فلو اصبح ارتفاع السطر هو الارتفاع الافتراضي، لا يوجد داعي من حجز قيمته في المصفوفة.

يمكنك تطوير الفئة السابقة بالطريقة التي تحلو لك، فقد تستخدم اسلوب الملفات المؤقتة لحفظ البيانات الكبيرة، او تعديل في انجاز الاكواد، لكن احذر تعديل واجهة الفئة، فالاداة Vb4arabGrid تستخدمها كما في الفقرة التالية.

ثانيا: تصميم الاداة Vb4arabGrid
وهي اهم اقسام البرنامج، فهي ستعرض وترسم الجدول استنادا الى الكائن المشتق من الفئة CData، فلو اردت تغيير ورقة العمل Sheet وعرضها في اداة التحكم، استخدام الخاصية CurrentSheet المحضونة في اداة التحكم:
code:
' Vb4arabGrid اداة التحكم
Public CurrentSheet As CData    ' كائن يمثل بيانات ورقة العمل الحالية
...
...
...



' قد تكتب شيئا مثل
If .... Then
	Set Vb4arabGrid.CurrentSheet = Sales
Else
	Set Vb4arabGrid.CurrentSheet = Finance
End If


الغ الخاصية AutoRedraw واجعل قيمتها الى False، فنحن لسنا اطفالا لنجعل Visual Basic يعيد الرسم عنا. وبالنسبة للخاصية ClipControls فيفضل تعديلها الى False حتى تزيد من سرعة تنفيذ اكواد طرق الرسم كـ Line وغيرها.
السؤال الذي يطرح نفسه الان، كيف سنرسم الاعمدة والسطور؟ والجواب بكل بساطة ابدأ من العمود 1 حتى 2147483647 ومن السطر 1 الى 2147483647، قد تكون اجابة صحيحة، الا ان المستخدم سيضطر الى الانتظار فترة ما تقارب اسبوع عند فتح جدول جديد، لهذا السبب سنقوم بتطبيق اسلوب برمجي يعرف بالتنفيذ عند الطلب On Demand Execution.
الفكرة من هذا المبدأ او الاسلوب هي عملية تنفيذ الاكواد عند الحاجة لعرضها فقط على عين المستخدم، فمثلا لو اردت عرض جميع المجلدات في القرص الصلب على اداة الشجرة TreeView، فلايوجد داعي للقيام بالبحث عن جميع المجلدا الفرعية ما دامت الاداة لا تعرض الا المجلدات الجذرية Root Directory، لذلك سنبحث عن المجلدات في الدليل الجذري فقط لزيادة السرعة، وعندما يقوم المستخدم بالنقر على عنصر Node من عناصر هذه القائمة فسنبدأ بالبحث عن المجلدات الفرعية الموجودة في ذلك العنصر Node، ولن يشعر المستخدم بهذه العملية.

وهذا بالضبط الذي سنفعله مع الاداة Vb4arabGrid، حيث لن نرسم الا المنطقة الظاهرة لعين المستخدم كما بالشكل التالي:



حيث يكون لدينا متغيران يوضحان اول عمود مطلوب رسمه واول سطر مطلوب رسمه في المتغيرات التالية:

code:
Private lStartByColNum As Long   ' رقم العمود الابتدائي للرسم
Private lStartByRowNum As Long   ' رقم السطر الابتدائي للرسم


بالنسبة لعملية طباعة نصوص الخلايا، فمن الضروري تعديل الاجراء ()PrintCells:
code:
Private Sub PrintCells()
    ' رسم محتويات الخلايا
    Dim lCounter As Long
    Dim lCounter2 As Long
    
    
    picSheet.CurrentY = CurrentSheet.RowHeight(0)
    picSheet.ForeColor = vbBlack
    
    
    For lCounter = lStartByRowNum To lStartByRowNum + 20
        picSheet.CurrentX = picSheet.ScaleWidth - CurrentSheet.ColWidth(0) - _ 
picSheet.TextWidth(CurrentSheet.CellText(lStartByColNum, lCounter)) - 1
        For lCounter2 = lStartByColNum To lStartByColNum + 20
            picSheet.Print CurrentSheet.CellText(lCounter2, lCounter);
            picSheet.CurrentX = picSheet.CurrentX - CurrentSheet.ColWidth(lCounter2) - _ 
picSheet.TextWidth(CurrentSheet.CellText(lCounter2 + 1, lCounter))
        Next
        picSheet.CurrentY = picSheet.CurrentY + CurrentSheet.RowHeight(lCounter)
    Next
End Sub


فلم اقم بكتابة اكواد اضافية لاجراء عملية الالتفاف التلقائي World Wrap للنص وبالذات اذا زاد حجم النص عن عرض العمود، ولم اضف اكواد لتنسيق محاذاة النصوص على الخلايا، فعي بشكل ثابت ستكون من اليمين الى اليسار.



فكما تلاحظ في الشكل السابق، نص الخلية 2 - 8 طويل جدا وقد امتدت الى الخلية 3 - 8 حتى تبعثرت الحروف.


ثالثا: البرنامج الرئيسي Vb4arab Excel
والان كل ما عليك هو استخدام اداة التحكم Vb4arabGrid ووضعها في النافذة الرئيسية للبرنامج، اضف ايضا خانة نص TextBox حتى تمكن المستخدم من الكتابة في الخلايا، وقم باضافة الكود اللازمة في احداث لوحة المفاتيح لتعطي المستخدمة قدرة على التنقل بين الخلايا باستخدام مفاتيح الاسهم.


اخيرا، كان الهدف من هذا الدرس اعطائك فكرة عامة عن طرق تصميم ادوات الجداول، بامكانك تطوير طرق اكثر مرونة وفعالية من هذه الطريقة باستخدام اجراءات API متقدمة حتى تزيد من سرعة ودقة تنفيذ الاكواد. اذا اعجبت في Vb4arab Excel واردت تطويرها بحيث يقبل تنسيقات مختلفة للخلايا كالخطوط، الالوان ... الخ او تطبيق معادلات رياضية A1=A2+A4 فعليك اختيار المكان المناسب لها، ولا تدمج كل الاكواد في فئة واحدة حتى لا تختلط الانساب وتضيع المحارم.
بامكانك الحصول على الانجاز الكامل لبرنامج Vb4arab Excel واداة التحكم Vb4arabGrid بالضغط على هذا الرابط. وبصراحة شديدة سيسرني جدا ان شددت عزيمك لتحصل على شرف اول مطور عربي يصمم برنامج للجداول الممتدة SpeardSheet، ولا تقلق فلن اطالبك بحقوق التأليف فاعتبر Vb4arab Excel هدية متواضعة مني لك.

ابتسم دائما، فانت مبرمج Visual Basic



ملحوظة: المقال كتبه مشرف منتدى فيجوال بيسك الأخ تركي العسيري

 

أرسلت في Monday, August 12 @ 03:37:28 AST بواسطة (عاصفة)



 


أكثر مقال تمت قراءته في موضوع (مقالات ودروس عامة):
صمم Microsoft Excel بنفسك !!!



صفحة للطباعة  صفحة للطباعة

أرسل هذا المقال لصديق  أرسل هذا المقال لصديق